﻿using System.Collections.Generic;
using System.Threading;

namespace Freedom.Common.Collections
{
    /// <summary>
    /// ObjectCollector Thread save object collector 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ObjectCollector<T>
    {
        #region Properties
        /// <summary>
        /// Items
        /// </summary>
        protected readonly List<T> Items = new List<T>();
        /// <summary>
        /// SyncRoot
        /// </summary>
        protected readonly ReaderWriterLockSlim Lock = new ReaderWriterLockSlim();
        private readonly T[] _empty = new T[0];

        /// <summary>
        /// Gets a value indicating whether this instance is empty.
        /// </summary>
        /// <value><c>true</c> if this instance is empty; otherwise, <c>false</c>.</value>
        public bool IsEmpty
        {
            get
            {
                if (!Lock.TryEnterReadLock(100)) return true;
                try
                {
                    return Items.Count == 0;
                }
                finally
                {
                    Lock.ExitReadLock();
                }
            }
        }
        /// <summary>
        /// Gets the count.
        /// </summary>
        /// <value>The count.</value>
        public int? Count
        {
            get
            {
                if (!Lock.TryEnterReadLock(100)) return null;
                try
                {
                    return Items.Count;
                }
                finally
                {
                    Lock.ExitReadLock();
                }
            }
        } 
        #endregion

        /// <summary>
        /// Puts the specified item.
        /// </summary>
        /// <param name="item">The item.</param>
        public virtual void Put(T item)
        {
            Lock.EnterWriteLock();
            try
            {
                Items.Add(item);
            }
            finally
            {
                Lock.ExitWriteLock();
            }
        }


        /// <summary>
        /// Puts the specified item.
        /// </summary>
        /// <param name="items">The items.</param>
        public virtual void Put(IEnumerable<T> items)
        {
            if (items==null) return;

            Lock.EnterWriteLock();
            try
            {
                Items.AddRange(items);
            }
            finally
            {
                Lock.ExitWriteLock();
            }
        }

        /// <summary>
        /// Exctracts all.
        /// </summary>
        /// <returns></returns>
        public T[] ExctractAll()
        {
            if (!Lock.TryEnterWriteLock(100)) return _empty;

            try
            {
                var result = Items.ToArray();
                Items.Clear();
                return result;
            }
            finally
            {
                Lock.ExitWriteLock();
            }
        }

    }
}


